﻿// © Benn Eichhorn 2010
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algobox.Feeds.Finance.Bats.PitchClient
{
    internal static class BatsMessageParser
    {
        static BatsMessageParser()
        {
            Date = DateTime.Today;
        }

        public const int S_TIMESTAMP_LOC = 1;
        public const int S_TIMESTAMP_LEN = 8;
        const int S_MESSAGETYPE_LOC = 9;

        /// <summary>
        /// Order Add Short
        /// </summary>
        const int S_A_LEN = 46;

        /// <summary>
        /// Order Add Long  
        /// </summary>      
        const int S_a_LEN = 59;

        /// <summary>
        /// Order Execution Short
        /// </summary>
        const int S_E_LEN = 40;

        /// <summary>
        /// Order Execution Long
        /// </summary>
        const int S_e_LEN = 44;

        /// <summary>
        /// Order Cancel Short
        /// </summary>
        const int S_X_LEN = 28;

        /// <summary>
        /// Order Cancel Long
        /// </summary>
        const int S_x_LEN = 32;

        /// <summary>
        /// Trade Message Short
        /// </summary> 
        const int S_P_LEN = 57;

        /// <summary>
        /// Trade Message Long
        /// </summary> 
        const int S_p_LEN = 70;


        /// <summary>
        /// Todays date
        /// </summary>
        public static readonly DateTime Date;

        internal static bool TryParseMessage(ref string inbound, ref Messages.IMessage message)
        {
            // inbound will always be >= 1 which means MESSAGETYPE_LOC will always be there so no need to check for it

            if (inbound.Length < S_MESSAGETYPE_LOC)
            {
                message = Messages.Error.GetInstance("Sequenced message failed minimum length check of " + S_MESSAGETYPE_LOC, ref inbound);
                return false;
            }

            switch (inbound[S_MESSAGETYPE_LOC])
            {
                // Order Add
                case 'A':
                    if (inbound.Length != S_A_LEN)
                    {
                        message = Messages.Error.GetInstance("OrderAdd failed message length check of " + S_A_LEN, ref inbound);
                        return false;
                    }
                    message = Messages.OrderAdd.ParseShort(ref inbound);
                    return (message is Messages.OrderAdd);


                // Order Add Long
                case 'a':
                    if (inbound.Length != S_a_LEN)
                    {
                        message = Messages.Error.GetInstance("OrderAdd failed message length check of " + S_A_LEN, ref inbound);
                        return false;
                    }
                    message = Messages.OrderAdd.ParseLong(ref inbound);
                    return (message is Messages.OrderAdd);


                case 'E':
                    if (inbound.Length != S_E_LEN)
                    {
                        message = Messages.Error.GetInstance("OrderExecution (short) failed message length check of " + S_E_LEN, ref inbound);
                        return false;
                    }
                    message = Messages.OrderExecution.ParseShort(ref inbound);
                    return (message is Messages.OrderExecution);


                case 'e':
                    if (inbound.Length != S_e_LEN)
                    {
                        message = Messages.Error.GetInstance("OrderExecution (long) failed message length check of " + S_e_LEN, ref inbound);
                        return false;
                    }
                    message = Messages.OrderExecution.ParseLong(ref inbound);
                    return (message is Messages.OrderExecution);


                // Order Cancel - S43751039X    49572 1418
                case 'X':
                    if (inbound.Length != S_X_LEN)
                    {
                        message = Messages.Error.GetInstance("OrderCancel (short) failed message length check of " + S_X_LEN, ref inbound);
                        return false;
                    }
                    message = Messages.OrderCancel.ParseShort(ref inbound);
                    return (message is Messages.OrderCancel);


                case 'x':
                    if (inbound.Length != S_x_LEN)
                    {
                        message = Messages.Error.GetInstance("OrderCancel (long) failed message length check of " + S_x_LEN, ref inbound);
                        return false;
                    }
                    message = Messages.OrderCancel.ParseLong(ref inbound);
                    return (message is Messages.OrderCancel);


                // Trade (short) - Ignored - S49818878P    80298B  1399AGNa       50140      110
                case 'P':
                    if (inbound.Length != S_P_LEN)
                    {
                        message = Messages.Error.GetInstance("TradeMessage (short) failed message length check of " + S_P_LEN, ref inbound);
                        return false;
                    }
                    message = Messages.Trade.ParseShort(ref inbound);
                    return (message is Messages.Trade);


                // Trade (long) - Ignored
                case 'p':
                    if (inbound.Length != S_p_LEN)
                    {
                        message = Messages.Error.GetInstance("TradeMessage (long) failed message length check of " + S_p_LEN, ref inbound);
                        return false;
                    }
                    message = Messages.Trade.ParseLong(ref inbound);
                    return (message is Messages.Trade);


                // Broken Trade - Ignored
                case 'B':
                    //message = Messages.Error.GetInstance("SquencedData MessageType B ignored", inbound);
                    return false;

                default:
                    message = Messages.Error.GetInstance("SquencedData MessageType " + inbound[S_MESSAGETYPE_LOC] + " not yet implemented", ref inbound);
                    return false;
            }

        }

    }
}
